home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / programr / ole2book.zip / CHAP04.ZIP / CHAP04 / DKOALA / DKOALA.CPP next >
C/C++ Source or Header  |  1993-04-13  |  8KB  |  344 lines

  1. /*
  2.  * DKOALA.CPP
  3.  *
  4.  * Example object implemented in a DLL.  This object supports
  5.  * IUnknown and IPersist interfaces, meaning it doesn't know anything more
  6.  * than how to return its class ID, but it demonstrates how any object
  7.  * is presented inside an DLL.
  8.  *
  9.  * Copyright (c)1993 Microsoft Corporation, All Rights Reserved
  10.  *
  11.  * Kraig Brockschmidt, Software Design Engineer
  12.  * Microsoft Systems Developer Relations
  13.  *
  14.  * Internet  :  kraigb@microsoft.com
  15.  * Compuserve:  >INTERNET:kraigb@microsoft.com
  16.  */
  17.  
  18.  
  19. //Must do this once in the entire build or we can't define our own GUIDs
  20. #define INITGUIDS
  21.  
  22. #include "dkoala.h"
  23.  
  24.  
  25. //Count number of objects and number of locks.
  26. ULONG       g_cObj=0;
  27. ULONG       g_cLock=0;
  28.  
  29.  
  30. /*
  31.  * LibMain
  32.  *
  33.  * Purpose:
  34.  *  DLL-specific entry point called from LibEntry.
  35.  *
  36.  * Parameters:
  37.  *  hInst           HINSTANCE instance of the DLL.
  38.  *  wDataSeg        WORD segment selector of the DLL's data segment.
  39.  *  wHeapSize       WORD byte count of the heap.
  40.  *  lpCmdLine       LPSTR to command line used to start the module.
  41.  *
  42.  * Return Value:
  43.  *  HANDLE          Instance handle of the DLL.
  44.  *
  45.  */
  46.  
  47. HANDLE FAR PASCAL LibMain(HINSTANCE hInst, WORD wDataSeg
  48.     , WORD cbHeapSize, LPSTR lpCmdLine)
  49.     {
  50.     if (0!=cbHeapSize)
  51.         UnlockData(0);
  52.  
  53.     return hInst;
  54.     }
  55.  
  56.  
  57.  
  58.  
  59.  
  60. /*
  61.  * WEP
  62.  *
  63.  * Purpose:
  64.  *  Required DLL Exit function.  Does nothing.
  65.  *
  66.  * Parameters:
  67.  *  bSystemExit     BOOL indicating if the system is being shut
  68.  *                  down or the DLL has just been unloaded.
  69.  *
  70.  * Return Value:
  71.  *  void
  72.  *
  73.  */
  74.  
  75. void FAR PASCAL WEP(int bSystemExit)
  76.     {
  77.     return;
  78.     }
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85. /*
  86.  * DllGetClassObject
  87.  *
  88.  * Purpose:
  89.  *  Provides an IClassFactory for a given CLSID that this DLL is
  90.  *  registered to support.  This DLL is placed under the CLSID
  91.  *  in the registration database as the InProcServer.
  92.  *
  93.  * Parameters:
  94.  *  clsID           REFCLSID that identifies the class factory desired.
  95.  *                  Since this parameter is passed this DLL can handle
  96.  *                  any number of objects simply by returning different
  97.  *                  class factories here for different CLSIDs.
  98.  *
  99.  *  riid            REFIID specifying the interface the caller wants
  100.  *                  on the class object, usually IID_ClassFactory.
  101.  *
  102.  *  ppv             LPVOID FAR * in which to return the interface pointer.
  103.  *
  104.  * Return Value:
  105.  *  HRESULT         NOERROR on success, otherwise contains an error SCODE.
  106.  */
  107.  
  108. HRESULT __export FAR PASCAL DllGetClassObject(REFCLSID rclsid, REFIID riid
  109.     , LPVOID FAR *ppv)
  110.     {
  111.     if (!IsEqualCLSID(rclsid, CLSID_Koala))
  112.         return ResultFromScode(E_FAIL);
  113.  
  114.     //Check that we can provide the interface
  115.     if (!IsEqualIID(riid, IID_IUnknown) && !IsEqualIID(riid, IID_IClassFactory))
  116.         return ResultFromScode(E_NOINTERFACE);
  117.  
  118.     //Return our IClassFactory for Koala objects
  119.     *ppv=(LPVOID)new CKoalaClassFactory();
  120.  
  121.     if (NULL==*ppv)
  122.         return ResultFromScode(E_OUTOFMEMORY);
  123.  
  124.     //Don't forget to AddRef the object through any interface we return
  125.     ((LPUNKNOWN)*ppv)->AddRef();
  126.  
  127.     return NOERROR;
  128.     }
  129.  
  130.  
  131.  
  132.  
  133.  
  134. /*
  135.  * DllCanUnloadNow
  136.  *
  137.  * Purpose:
  138.  *  Answers if the DLL can be freed, that is, if there are no
  139.  *  references to anything this DLL provides.
  140.  *
  141.  * Parameters:
  142.  *  None
  143.  *
  144.  * Return Value:
  145.  *  BOOL            TRUE if nothing is using us, FALSE otherwise.
  146.  */
  147.  
  148. STDAPI DllCanUnloadNow(void)
  149.     {
  150.     SCODE   sc;
  151.  
  152.     //Our answer is whether there are any object or locks
  153.     sc=(0L==g_cObj && 0==g_cLock) ? S_OK : S_FALSE;
  154.     return ResultFromScode(sc);
  155.     }
  156.  
  157.  
  158.  
  159.  
  160. /*
  161.  * ObjectDestroyed
  162.  *
  163.  * Purpose:
  164.  *  Function for the Koala object to call when it gets destroyed.
  165.  *  Since we're in a DLL we only track the number of objects here
  166.  *  letting DllCanUnloadNow take care of the rest.
  167.  *
  168.  * Parameters:
  169.  *  None
  170.  *
  171.  * Return Value:
  172.  *  None
  173.  */
  174.  
  175. void FAR PASCAL ObjectDestroyed(void)
  176.     {
  177.     g_cObj--;
  178.     return;
  179.     }
  180.  
  181.  
  182.  
  183.  
  184.  
  185. /*
  186.  * CKoalaClassFactory::CKoalaClassFactory
  187.  * CKoalaClassFactory::~CKoalaClassFactory
  188.  *
  189.  * Constructor Parameters:
  190.  *  None
  191.  */
  192.  
  193. CKoalaClassFactory::CKoalaClassFactory(void)
  194.     {
  195.     m_cRef=0L;
  196.     return;
  197.     }
  198.  
  199.  
  200. CKoalaClassFactory::~CKoalaClassFactory(void)
  201.     {
  202.     return;
  203.     }
  204.  
  205.  
  206.  
  207.  
  208.  
  209.  
  210. /*
  211.  * CKoalaClassFactory::QueryInterface
  212.  * CKoalaClassFactory::AddRef
  213.  * CKoalaClassFactory::Release
  214.  */
  215.  
  216. STDMETHODIMP CKoalaClassFactory::QueryInterface(REFIID riid, LPVOID FAR *ppv)
  217.     {
  218.     *ppv=NULL;
  219.  
  220.     //Any interface on this object is the object pointer.
  221.     if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IClassFactory))
  222.         *ppv=(LPVOID)this;
  223.  
  224.     /*
  225.      * If we actually assign an interface to ppv we need to AddRef it
  226.      * since we're returning a new pointer.
  227.      */
  228.     if (NULL!=*ppv)
  229.         {
  230.         ((LPUNKNOWN)*ppv)->AddRef();
  231.         return NOERROR;
  232.         }
  233.  
  234.     return ResultFromScode(E_NOINTERFACE);
  235.     }
  236.  
  237.  
  238. STDMETHODIMP_(ULONG) CKoalaClassFactory::AddRef(void)
  239.     {
  240.     return ++m_cRef;
  241.     }
  242.  
  243.  
  244. STDMETHODIMP_(ULONG) CKoalaClassFactory::Release(void)
  245.     {
  246.     ULONG           cRefT;
  247.  
  248.     cRefT=--m_cRef;
  249.  
  250.     if (0L==m_cRef)
  251.         delete this;
  252.  
  253.     return cRefT;
  254.     }
  255.  
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262. /*
  263.  * CKoalaClassFactory::CreateInstance
  264.  *
  265.  * Purpose:
  266.  *  Instantiates a Koala object that supports the IPersist
  267.  *  and IUnknown interfaces.  If the caller asks for a different
  268.  *  interface than these two then we fail.
  269.  *
  270.  * Parameters:
  271.  *  punkOuter       LPUNKNOWN to the controlling IUnknown if we are
  272.  *                  being used in an aggregation.
  273.  *  riid            REFIID identifying the interface the caller desires
  274.  *                  to have for the new object.
  275.  *  ppvObj          LPVOID FAR * in which to store the desired interface
  276.  *                  pointer for the new object.
  277.  *
  278.  * Return Value:
  279.  *  HRESULT         NOERROR if successful, otherwise contains E_NOINTERFACE
  280.  *                  if we cannot support the requested interface.
  281.  */
  282.  
  283. STDMETHODIMP CKoalaClassFactory::CreateInstance(LPUNKNOWN punkOuter
  284.     , REFIID riid, LPVOID FAR *ppvObj)
  285.     {
  286.     LPCKoala            pObj;
  287.     HRESULT             hr;
  288.  
  289.     *ppvObj=NULL;
  290.     hr=ResultFromScode(E_OUTOFMEMORY);
  291.  
  292.     //Verify that if there is a controlling unknown it's asking for IUnknown
  293.     if (NULL!=punkOuter && !IsEqualIID(riid, IID_IUnknown))
  294.         return ResultFromScode(E_NOINTERFACE);
  295.  
  296.     //Create the object telling it a function to notify us when it's gone.
  297.     pObj=new CKoala(punkOuter, ObjectDestroyed);
  298.  
  299.     if (NULL==pObj)
  300.         return hr;
  301.  
  302.     if (pObj->FInit())
  303.         hr=pObj->QueryInterface(riid, ppvObj);
  304.  
  305.     //Kill the object if initial creation or FInit failed.
  306.     if (FAILED(hr))
  307.         delete pObj;
  308.     else
  309.         g_cObj++;
  310.  
  311.     return hr;
  312.     }
  313.  
  314.  
  315.  
  316.  
  317.  
  318.  
  319. /*
  320.  * CKoalaClassFactory::LockServer
  321.  *
  322.  * Purpose:
  323.  *  Increments or decrements the lock count of the DLL.  If the lock
  324.  *  count goes to zero and there are no objects, the DLL is allowed
  325.  *  to unload.  See DllCanUnloadNow.
  326.  *
  327.  * Parameters:
  328.  *  fLock           BOOL specifying whether to increment or decrement the
  329.  *                  lock count.
  330.  *
  331.  * Return Value:
  332.  *  HRESULT         NOERROR always.
  333.  */
  334.  
  335. STDMETHODIMP CKoalaClassFactory::LockServer(BOOL fLock)
  336.     {
  337.     if (fLock)
  338.         g_cLock++;
  339.     else
  340.         g_cLock--;
  341.  
  342.     return NOERROR;
  343.     }
  344.